﻿using Aspfm.Main;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace AspfmWinForm
{
    delegate void InitAspfmServices();
    public class ClientResult
    {
        public ClientResult() { }
        public void Init(string html)
        {
            _HtmlJson = html;
            WebResultList = WebResultList.DeserializeObject(html);
        }
        private string _HtmlJson = "";
        /// <summary>
        /// 错误信息。Success=false时，才有值
        /// </summary>
        public string ErrMsg = "";
        /// <summary>
        /// 调用服务是否成功。
        /// </summary>
        public bool Success = true;
        /// <summary>
        /// 服务返回的JSON。
        /// </summary>
        public string HtmlJson {  get { return _HtmlJson; } }
        /// <summary>
        /// 服务返回的JSON转化之后的对象。
        /// 建议服务接口，一定要返回数据对象。不然很难分辨服务返回的信息是提示信息还是其他的信息。
        /// </summary>
        public WebResultList WebResultList = null;

        public WebResult WebResult {
            get {
                if (WebResultList != null && WebResultList.BWebResult != null)
                {
                    if (WebResultList.BWebResult.Count > 0)
                    {
                        return WebResultList.BWebResult[0];
                    }
                }
                return null;
            }
        }
    }
    /// <summary>
    /// 激活AspfmServices接口,可以解决第一次调用接口慢的问题。由于aspfm服务端设计优良。性能一定比webapi,mvc,webservice好。
    /// </summary>
    public class ClientServices
    {
        public ClientServices(string loginMiwen,string _urlconfig = "站点URL")
        {
            _loginMiwen = loginMiwen;
            urlconfig = _urlconfig;
            ////启用异步初始化AspfmServices
            //InitAspfmServices handler = new InitAspfmServices(_InitAspfmServices);
            //handler.BeginInvoke(null, null);
           // InitAspfmServices();
        }

        private string _loginMiwen = "";

        public string LoginMiwen
        {
            get { return _loginMiwen; }
        }

        private string urlconfig = "站点URL";
        public static T DeserializeDynamic<T>(string json)
        {
            return WebResultList.DeserializeDynamic<T>(json);
        }
        //public string ServicesUrl { get { return "http://127.0.0.1:8090/Aspfm.Server/Aspfm"; } }
        public string ServicesUrl { get { return PageTool.GetAspfmConfig(urlconfig, "url").Trim('/') + "/AspfmAshx.ashx"; } }
        private string ServicesUser { get { return PageTool.GetAspfmConfig(urlconfig, "user"); } }
        private string ServicesPassword { get { return PageTool.GetAspfmConfig(urlconfig, "password"); } }

        public void InitAspfmServices()
        {
            _CreatePostHttpResponse("Aspfm.Login", "Aspfm.Login.Login", "login");
        }
        private bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受     
        }

        /// <summary>
        /// 关于接口数据通过网络传播，很容易被第三方代理拦截所有参数。
        /// 为了解决这个问题，研究了很久。发现只要部署AspfmServices站点的服务器，添加了域控。
        /// 接口数据在传播过程中，为自动被加解密。有效解决第三方代理拦截参数的问题。
        /// </summary>
        /// <param name="dll"></param>
        /// <param name="classname"></param>
        /// <param name="action"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public ClientResult CreatePostHttpResponse(string dll, string classname, string action,AspfmModel parameters = null)
        {
            if (string.IsNullOrEmpty(_loginMiwen))
            {
                ClientResult client = new ClientResult();
                client.Success = false;
                client.ErrMsg = "请先调用LoginServices接口登录。";
                return client;
            }
            return _CreatePostHttpResponse(dll, classname, action,parameters);
        }

        private ClientResult _CreatePostHttpResponse(string dll, string classname, string action, AspfmModel parameters = null)
        {
            ClientResult clientResult = new ClientResult();
            HttpWebRequest request = null;
            try
            {
                StringBuilder buffer = new StringBuilder();
                buffer.AppendFormat("{0}={1}", "fmparams.Dll", dll);
                buffer.AppendFormat("&{0}={1}", "fmparams.Class", classname);
                buffer.AppendFormat("&{0}={1}", "fmparams.Active", action);
                buffer.AppendFormat("&{0}={1}", "fmparams.loginMiwen", _loginMiwen);
                //HTTPSQ请求  
                if (ServicePointManager.ServerCertificateValidationCallback == null)
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                }
                request = WebRequest.Create(ServicesUrl) as HttpWebRequest;
                request.PreAuthenticate = true;
                request.Credentials = new NetworkCredential(ServicesUser, ServicesPassword);
                //request.CookieContainer = cookie;
                request.ProtocolVersion = HttpVersion.Version10;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";
                //如果需要POST数据     
                if (!(parameters == null || parameters.Values.Count == 0))
                {
                    foreach (string key in parameters.Values.Keys)
                    {
                        buffer.AppendFormat("&{0}={1}", key, parameters.Values[key]);
                    }
                }
                byte[] data = Encoding.UTF8.GetBytes(buffer.ToString());
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
                using (WebResponse response = request.GetResponse())
                {
                    //打印返回值  
                    using (Stream stream1 = response.GetResponseStream())   //获取响应的字符串流  
                    {
                        StreamReader sr = new StreamReader(stream1); //创建一个stream读取流  
                        clientResult.Init(sr.ReadToEnd()); //从头读到尾，放到字符串html  
                    }
                    response.Close();
                }
                request.Abort();
                return clientResult;
            }
            catch(WebException ex)
            {
                clientResult.Success = false;
                clientResult.ErrMsg = ex.Message;
                if (ex.Response != null && ex.Response is HttpWebResponse)
                {
                    StreamReader sr = new StreamReader(((HttpWebResponse)ex.Response).GetResponseStream(),Encoding.UTF8);
                    Loger.WriteLog(LogType.ErrLog, sr.ReadToEnd(), "", false);
                    sr.Close();
                    ex.Response.Close();
                }
                return clientResult;
            }
        }

        public ClientResult LoginServices(string user, string password)
        {
            AspfmModel aspfmmode = new AspfmModel();
            aspfmmode.SetPropertyValue("loginuser",user);
            aspfmmode.SetPropertyValue("loginpassword", password);
            aspfmmode.SetPropertyValue("logintype", "csclient");
            ClientResult clientResult = _CreatePostHttpResponse("Aspfm.Login", "Aspfm.Login.Login", "login", aspfmmode);
            if (clientResult.WebResult != null)
            {
                if (clientResult.WebResult.Success)
                {
                    _loginMiwen = clientResult.WebResult.Result.GetPropertyValueStr("loginMiwen");
                }
            }
            return clientResult;
        }
    }
}
